from python_ai.common.xcommon import sep
import numpy as np
import pandas as pd

"""\
0      airplane
1    automobile
2          bird
3           cat
4          deer
5           dog
6          frog
7         horse
8          ship
9         truck
"""

# load lables' name
sep('lables name')
labels = pd.read_csv(r'../../../../large_data/DL1/cifar-10-batches-bin/batches.meta.txt',
                     sep=r'\n',
                     engine='python',
                     encoding='utf8',
                     header=None
                     ).iloc[:, 0]
print(labels)

"""\
Binary version The binary version contains the files data_batch_1.bin, data_batch_2.bin, ..., data_batch_5.bin, 
as well as test_batch.bin. Each of these files is formatted as follows: 
<1 x label><3072 x pixel>  
... 
<1 x label><3072 x pixel> 

# 1 + (r: 32r * 32c) + (g: 32r * 32c) + (b: 32r * 32c)  # 1 + 3 x 32 x 32
In other words, the first byte is the label of the first image, which is a number in the range 
0-9. The next 3072 bytes are the values of the pixels of the image. The first 1024 bytes are the red channel values, 
the next 1024 the green, and the final 1024 the blue. The values are stored in row-major order, so the first 32 bytes 
are the red channel values of the first row of the image. 

Each file contains 10000 such 3073-byte "rows" of images, although there is nothing delimiting the rows. Therefore 
each file should be exactly 30730000 bytes long. 

There is another file, called batches.meta.txt. This is an ASCII file that maps numeric labels in the range 0-9 to 
meaningful class names. It is merely a list of the 10 class names, one per row. The class name on row i corresponds 
to numeric label i. """

# load data
def load_m_data(m, offset=0):
    sep('load data')
    onesize = 1 + 32 * 32 * 3  # 图片的特征X=32*32*3 类别y占1位
    with open(r'../../../../large_data/DL1/cifar-10-batches-bin/data_batch_1.bin', 'br') as f:
        f.seek(offset * onesize)
        buff = f.read(m * onesize)
        data = np.frombuffer(buff, dtype=np.uint8).reshape(-1, onesize)
        print(f'loaded: {data.shape}')

        # 1 + (r: 32r * 32c) + (g: 32r * 32c) + (b: 32r * 32c)  # 1 + 3 x 32 x 32
        data = np.hsplit(data, [1])
        y = data[0]
        print(f'y: {y.shape}')
        data = data[1]

        # organize channels
        print(f'image: {data.shape}')  # (m, 3072)
        data = data.reshape([-1, 3, 32, 32])
        print(f'images: {data.shape}')
        data = data.transpose([0, 2, 3, 1])
        print(f'images: {data.shape}')
        return y, data


if '__main__' == __name__:
    import matplotlib.pyplot as plt

    plt.figure(figsize=[16, 8])
    spr = 4  # subplot row
    spc = 8  # subplot column
    spn = 0

    y, x = load_m_data(spr * spc, 10000 - spr * spc)
    for i, pic in enumerate(x):
        spn += 1
        if spn > spr * spc:
            break
        plt.subplot(spr, spc, spn)
        plt.axis('off')
        lbl = labels[y[i, 0]]  # ATTENTION y is 10x1, y[i] is vector, y[i, 0] is scalar, this diff especially important when labels is a pandas Series
        plt.title(f'{lbl}')
        plt.imshow(pic)
